/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdint>
#include <string>
#include <cstdio>
#include <vector>

#include <ace/xcomponent/native_interface_xcomponent.h>
#include <hilog/log.h>

#include "manager.h"

namespace NativeXComponentSample {
#define TEST_TEXT_NUMBER 20

ArkUI_NodeHandle gTextBuf[TEST_TEXT_NUMBER];
int gBarWidth = 10;

Manager Manager::manager_;
static ArkUI_NativeNodeAPI_1* nodeAPI;
static ArkUI_NodeHandle xc;

Manager::~Manager() {
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "~Manager");
    for (auto iter = nativeXComponentMap_.begin(); iter != nativeXComponentMap_.end(); ++iter) {
        if (iter->second != nullptr) {
            delete iter->second;
            iter->second = nullptr;
        }
    }
    nativeXComponentMap_.clear();
    for (auto iter = nativeNodeMap_.begin(); iter != nativeNodeMap_.end(); ++iter) {
        if (iter->second != nullptr) {
            delete iter->second;
            iter->second = nullptr;
        }
    }
    nativeNodeMap_.clear();

    for (auto iter = containerMap_.begin(); iter != containerMap_.end(); ++iter) {
        if (iter->second != nullptr) {
            delete iter->second;
            iter->second = nullptr;
        }
    }
    containerMap_.clear();
}

ArkUI_NodeHandle testStackExample() {
    ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_SCROLL);
    ArkUI_NodeHandle stack = nodeAPI->createNode(ARKUI_NODE_STACK);
    ArkUI_NodeHandle text = nodeAPI->createNode(ARKUI_NODE_TEXT);
    ArkUI_NumberValue value[] = {480};
    ArkUI_AttributeItem item = {value, 1};
    ArkUI_AttributeItem content = { .string = "cpi demo" }; 
    nodeAPI->setAttribute(scroll, NODE_WIDTH, &item);
    nodeAPI->setAttribute(stack, NODE_WIDTH, &item);
    value[0].f32 = 300;
    nodeAPI->setAttribute(scroll, NODE_HEIGHT, &item);
    value[0].f32 = 300;
    nodeAPI->setAttribute(stack, NODE_HEIGHT, &item);
    value[0].u32 = 0xFFFF0000;
    nodeAPI->setAttribute(stack, NODE_BACKGROUND_COLOR, &item);
    nodeAPI->setAttribute(text, NODE_TEXT_CONTENT, &content);
    nodeAPI->registerNodeEvent(scroll, NODE_SCROLL_EVENT_ON_SCROLL, 1);
    nodeAPI->registerNodeEvent(text, NODE_ON_CLICK, 2);
    auto onScroll = [](ArkUI_NodeEvent *event) {
       if (event->eventId == 1) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "capi on Scroll Y: %{public}f", event->componentEvent.data[1].f32);
       }
        if (event->eventId == 2) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "capi on Click");
        }
    };
    nodeAPI->registerNodeEventReceiver(onScroll);
    nodeAPI->addChild(stack, text);
    nodeAPI->addChild(scroll, stack);
    return scroll;
}

//ArkUI_NodeHandle testLoadingProgressExample() {
//    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
//    ArkUI_NumberValue value[] = {480};
//
//    ArkUI_AttributeItem item = {value, 1};
//    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
//    value[0].f32 = 10;
//    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
//    ArkUI_NodeHandle loadingProgress = nodeAPI->createNode(ARKUI_NODE_LOADING_PROGRESS);
//    value[0].u32 = 0xFF0000ff;
//    nodeAPI->setAttribute(loadingProgress, NODE_LOADING_PROGRESS_COLOR, &item);
//    auto retItem = nodeAPI->getAttribute(loadingProgress, NODE_LOADING_PROGRESS_COLOR);
//    nodeAPI->resetAttribute(loadingProgress, NODE_LOADING_PROGRESS_COLOR);
//    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "retItem.color=%d", retItem->value[0].u32);
//    value[0].i32 = false;
//    nodeAPI->setAttribute(loadingProgress, NODE_LOADING_PROGRESS_ENABLE_LOADING, &item);
//    nodeAPI->addChild(column, loadingProgress);
//    return column;
//}

ArkUI_NodeHandle testButtonExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};

    ArkUI_AttributeItem item = {value, 1};
    ArkUI_AttributeItem content = {.string="liyi\ngggg"};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    ArkUI_NodeHandle button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    nodeAPI->setAttribute(button, NODE_BUTTON_LABEL, &content);
    value[0].u32 = 0xffff0000;
    nodeAPI->registerNodeEvent(button, NODE_ON_CLICK, 1);
    auto onclick = [](ArkUI_NodeEvent *event) {
       if (event->eventId == 1) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "button click");
       }
    };
    nodeAPI->registerNodeEventReceiver(onclick);
    nodeAPI->addChild(column, button);
    return column;
}

ArkUI_NodeHandle testRefreshExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};

    ArkUI_AttributeItem item = {value, 1};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    ArkUI_NodeHandle refresh = nodeAPI->createNode(ARKUI_NODE_REFRESH);
    ArkUI_NodeHandle scroll = nodeAPI->createNode(ARKUI_NODE_SCROLL);
    value[0].i32 = 1;
    nodeAPI->setAttribute(refresh, NODE_REFRESH_REFRESHING, &item);
    nodeAPI->addChild(refresh, scroll);
    nodeAPI->addChild(column, refresh);
    return column;
}

ArkUI_NodeHandle testXComponentExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};
    ArkUI_NumberValue value2[] = {{.u32=10}, {.u32=10}};
    ArkUI_AttributeItem item = {value, 1, "liyixcomponent"};
    ArkUI_AttributeItem item2 = {value2, 2};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    xc = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT);
    ArkUI_NodeHandle button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    nodeAPI->setAttribute(button, NODE_BUTTON_LABEL, &item);
    value[0].i32 = ARKUI_XCOMPONENT_TYPE_SURFACE;
    nodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &item);
    nodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &item);
    nodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE, &item2);
    auto typeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_TYPE);
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "xcomponent type: %{public}d", typeRet->value[0].i32);
    auto idRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_ID);
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "xcomponent id: %{public}s", idRet->string);
    nodeAPI->registerNodeEvent(button, NODE_ON_CLICK, 1);
    auto onclick = [](ArkUI_NodeEvent *event) {
       if (event->eventId == 1) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "button click");
            auto sizeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE);
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "xcomponent size: %{public}u", sizeRet->value[0].u32);
       }
    };
    nodeAPI->registerNodeEventReceiver(onclick);
    nodeAPI->addChild(column, xc);
    nodeAPI->addChild(column, button);
    return column;
}

ArkUI_NodeHandle testTextInputExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};
    ArkUI_NumberValue value2[] = {480, 100};
    ArkUI_NumberValue value3[] = {16, {.i32=ARKUI_FONT_STYLE_ITALIC}, {.i32=ARKUI_FONT_WEIGHT_BOLDER}};
    ArkUI_AttributeItem item = {value, 1};
    ArkUI_AttributeItem item2 = {value2, 1};
    ArkUI_AttributeItem item3 = {value3, 3};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    ArkUI_NodeHandle stack = nodeAPI->createNode(ARKUI_NODE_STACK);
    value[0].f32 = 480;
    nodeAPI->setAttribute(stack, NODE_WIDTH, &item);
    value[0].f32 = 600;
    nodeAPI->setAttribute(stack, NODE_HEIGHT, &item);
    ArkUI_NodeHandle textinput = nodeAPI->createNode(ARKUI_NODE_TEXT_INPUT);
    ArkUI_NodeHandle button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
    auto manager = Manager::GetInstance();
    std::string capiId = "textinput";
    manager->SetNativeNode(capiId, textinput);
    ArkUI_AttributeItem content = {.string="click button"};
    nodeAPI->setAttribute(button, NODE_BUTTON_LABEL, &content);
    item.string = "placeholder";
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_PLACEHOLDER, &item);
    item.string = "input";
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_TEXT, &item);
    item.string = "textinput";
    nodeAPI->setAttribute(textinput, NODE_ID, &item);
    value[0].u32 = 0xFFFF0000;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_CARET_COLOR, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_CARET_STYLE, &item);
    value[0].i32 = 1;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_SHOW_UNDERLINE, &item);
    value[0].i32 = 10;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_MAX_LENGTH, &item);
    value[0].i32 = ARKUI_ENTER_KEY_TYPE_SEARCH;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_ENTER_KEY_TYPE, &item);
    value[0].u32 = napi_undefined;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_PLACEHOLDER_COLOR, &item);
    value3[0].f32 = 16;
    value3[1].i32 = ARKUI_FONT_STYLE_ITALIC;
    value3[2].i32 = ARKUI_FONT_WEIGHT_BOLDER;
    item3.string = "HarmonyOS Sans";
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_PLACEHOLDER_FONT, &item3);
    value[0].i32 = ARKUI_TEXTINPUT_TYPE_NORMAL;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_TYPE, &item);
    value[0].i32 = 1;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_ENABLE_KEYBOARD_ON_FOCUS, &item);
    value[0].i32 = 1;
    nodeAPI->setAttribute(textinput, NODE_DEFAULT_FOCUS, &item);
    value[0].u32 = 0xFF0000FF;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_SELECTED_BACKGROUND_COLOR, &item);
    value[0].i32 = 0;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_SHOW_PASSWORD_ICON, &item);
    value3[0].i32 = ARKUI_CANCELBUTTON_STYLE_INPUT;
    value3[1].f32 = 50;
    value3[2].u32 = 0xff000000;
    item3.string="";
    value2[0].i32 = ARKUI_CANCELBUTTON_STYLE_INPUT;
    value2[1].f32 = 50;
    nodeAPI->setAttribute(textinput, NODE_TEXT_INPUT_CANCEL_BUTTON, &item2);
    nodeAPI->registerNodeEvent(textinput, NODE_TEXT_INPUT_ON_CHANGE, 2);
        auto onclick = [](ArkUI_NodeEvent *event) {
           if (event->eventId == 2) {
                OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "textinput change");
           }
        };
    nodeAPI->registerNodeEventReceiver(onclick);
    nodeAPI->addChild(column, textinput);
    
    auto result = nodeAPI->getAttribute(textinput, NODE_TEXT_INPUT_SELECTED_BACKGROUND_COLOR);
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "textinput CARET COLOR: %{public}u", result->value[0].u32);
    
    return column;
}

//ArkUI_NodeHandle testTextAreaExample() {
//    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
//    ArkUI_NumberValue value[] = {480};
//    ArkUI_NumberValue value3[] = {16, {.i32=ARKUI_FONT_STYLE_ITALIC}, {.i32=ARKUI_FONT_WEIGHT_BOLDER}};
//    ArkUI_AttributeItem item = {value, 1};
//    ArkUI_AttributeItem item3 = {value3, 3};
//    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
//    value[0].f32 = 10;
//    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
//    ArkUI_NodeHandle textarea = nodeAPI->createNode(ARKUI_NODE_TEXT_AREA);
//    ArkUI_NodeHandle button = nodeAPI->createNode(ARKUI_NODE_BUTTON);
//    auto manager = Manager::GetInstance();
//    std::string capiId = "textarea";
//    manager->SetNativeNode(capiId, textarea);
//    ArkUI_AttributeItem content = {.string="click button"};
//    nodeAPI->setAttribute(button, NODE_BUTTON_LABEL, &content);
//    item.string = "placeholder";
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_PLACEHOLDER, &item);
//    item.string = "input";
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_TEXT, &item);
//    value[0].u32 = 0xFFFF0000;
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_CARET_COLOR, &item);
//    value[0].i32 = 10;
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_MAX_LENGTH, &item);
//    value[0].u32 = 0xFF000000;
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_PLACEHOLDER_COLOR, &item);
//    value3[0].f32 = 16;
//    value3[1].i32 = ARKUI_FONT_STYLE_ITALIC;
//    value3[2].i32 = ARKUI_FONT_WEIGHT_BOLDER;
//    item3.string = "HarmonyOS Sans";
//    nodeAPI->setAttribute(textarea, NODE_TEXT_AREA_PLACEHOLDER_FONT, &item3);
//    nodeAPI->registerNodeEvent(textarea, NODE_TEXT_AREA_ON_CHANGE, 2);
//    auto onclick = [](ArkUI_NodeEvent *event) {
//       if (event->eventId == 2) {
//            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "textarea %{public}s", event->stringEvent.pStr);
//       }
//    };
//    nodeAPI->registerNodeEventReceiver(onclick);
//    nodeAPI->addChild(column, textarea);
//    nodeAPI->addChild(column, button);
//    return column;
//}
//
ArkUI_NodeHandle testProgressExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};

    ArkUI_AttributeItem item = {value, 1};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    ArkUI_NodeHandle progress = nodeAPI->createNode(ARKUI_NODE_PROGRESS);
    item.string = "progress";
    nodeAPI->setAttribute(progress, NODE_ID, &item);
    value[0].f32 = 100;
    nodeAPI->setAttribute(progress, NODE_PROGRESS_TOTAL, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(progress, NODE_PROGRESS_VALUE, &item);
    value[0].u32 = 0xFFFF0000;
    nodeAPI->setAttribute(progress, NODE_PROGRESS_COLOR, &item);
    value[0].i32 = ARKUI_PROGRESS_ECLIPSE;
    nodeAPI->setAttribute(progress, NODE_PROGRESS_TYPE, &item);
    nodeAPI->addChild(column, progress);
    auto resultValue = nodeAPI->getAttribute(progress, NODE_PROGRESS_VALUE);
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "progress value: %{public}f", resultValue->value[0].f32);
    auto resultTotal = nodeAPI->getAttribute(progress, NODE_PROGRESS_TOTAL);
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "progress total: %{public}f", resultTotal->value[0].f32);
    return column;
}
//
ArkUI_NodeHandle testTextPickerExample() {
    ArkUI_NodeHandle column = nodeAPI->createNode(ARKUI_NODE_COLUMN);
    ArkUI_NumberValue value[] = {480};

    ArkUI_AttributeItem item = {value, 1};
    nodeAPI->setAttribute(column, NODE_WIDTH, &item);
    value[0].f32 = 10;
    nodeAPI->setAttribute(column, NODE_MARGIN, &item);
    ArkUI_NodeHandle textpicker = nodeAPI->createNode(ARKUI_NODE_TEXT_PICKER);
    item.string="textpicker";
    nodeAPI->setAttribute(textpicker, NODE_ID, &item);
    value[0].i32=ARKUI_TEXTPICKER_RANGETYPE_SINGLE;
    item.string="1;2;3;4";
    nodeAPI->setAttribute(textpicker, NODE_TEXT_PICKER_OPTION_RANGE, &item);
    value[0].i32=3;
    nodeAPI->setAttribute(textpicker, NODE_TEXT_PICKER_OPTION_SELECTED, &item);
    item.string = "2";
    nodeAPI->setAttribute(textpicker, NODE_TEXT_PICKER_OPTION_VALUE, &item);
    nodeAPI->addChild(column, textpicker);
    return column;
}

napi_value Manager::CreateNativeNode(napi_env env, napi_callback_info info) {
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN");
    if ((env == nullptr) || (info == nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null");
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 1");
    size_t argCnt = 1;
    napi_value args[1] = {nullptr};
    if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed");
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 2");

    if (argCnt != 1) {
        napi_throw_type_error(env, NULL, "Wrong number of arguments");
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 3");
    napi_valuetype valuetype;
    if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_typeof failed");
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 4");
    if (valuetype != napi_string) {
        napi_throw_type_error(env, NULL, "Wrong type of arguments");
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 5");

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    size_t length;
    if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 6");

    auto manager = Manager::GetInstance();
    if (manager == nullptr) {
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 7 idStr(%{public}s)", idStr);

    OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
    if (component == nullptr) {
        return nullptr;
    }
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI before");
    nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(OH_ArkUI_GetNativeAPI(ARKUI_NATIVE_NODE, 1));
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI after");
    if (nodeAPI != nullptr) {
        if (nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
            OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode 1");
            ArkUI_NodeHandle testNode;
            
//              testNode = testStackExample();
//            testNode = testLoadingProgressExample();
//            testNode = testButtonExample();
//            testNode = testRefreshExample();
//            testNode = testTextInputExample();
//            testNode = testTextAreaExample();
//            testNode = testProgressExample();
//            testNode = testTextPickerExample();
            testNode = testXComponentExample();
            
            OH_NativeXComponent_AttachNativeRootNode(component, testNode);
        }
    }
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode  555");
    return nullptr;
}

napi_value Manager::UpdateNativeNode(napi_env env, napi_callback_info info) {

    if ((env == nullptr) || (info == nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode env or info is null");
        return nullptr;
    }

    size_t argCnt = 1;
    napi_value args[1] = {nullptr};
    if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "UpdateNativeNode napi_get_cb_info failed");
    }

    if (argCnt != 1) {
        napi_throw_type_error(env, NULL, "Wrong number of arguments");
        return nullptr;
    }

    napi_valuetype valuetype;
    if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_typeof failed");
        return nullptr;
    }

    if (valuetype != napi_string) {
        napi_throw_type_error(env, NULL, "Wrong type of arguments");
        return nullptr;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    constexpr uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    size_t length;
    if (napi_get_value_string_utf8(env, args[0], idStr, idSize, &length) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
        return nullptr;
    }

    auto manager = Manager::GetInstance();
    if (manager == nullptr) {
        return nullptr;
    }

    OH_NativeXComponent *component = manager->GetNativeXComponent(idStr);
    if (component == nullptr) {
        return nullptr;
    }

    if ((env == nullptr) || (info == nullptr || component == nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
        return nullptr;
    }
    
    return nullptr;
}

napi_value Manager::GetContext(napi_env env, napi_callback_info info) {
    if ((env == nullptr) || (info == nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext env or info is null");
        return nullptr;
    }

    size_t argCnt = 1;
    napi_value args[1] = {nullptr};
    if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "GetContext napi_get_cb_info failed");
    }

    if (argCnt != 1) {
        napi_throw_type_error(env, NULL, "Wrong number of arguments");
        return nullptr;
    }

    napi_valuetype valuetype;
    if (napi_typeof(env, args[0], &valuetype) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_typeof failed");
        return nullptr;
    }

    if (valuetype != napi_number) {
        napi_throw_type_error(env, NULL, "Wrong type of arguments");
        return nullptr;
    }

    int64_t value;
    if (napi_get_value_int64(env, args[0], &value) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_get_value_int64 failed");
        return nullptr;
    }

    napi_value exports;
    if (napi_create_object(env, &exports) != napi_ok) {
        napi_throw_type_error(env, NULL, "napi_create_object failed");
        return nullptr;
    }

    return exports;
}

void Manager::Export(napi_env env, napi_value exports) {
    if ((env == nullptr) || (exports == nullptr)) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: env or exports is null");
        return;
    }

    napi_value exportInstance = nullptr;
    if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_get_named_property fail");
        return;
    }

    OH_NativeXComponent *nativeXComponent = nullptr;
    if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager", "Export: napi_unwrap fail");
        return;
    }

    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
    if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) !=
        OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Manager",
                     "Export: OH_NativeXComponent_GetXComponentId fail");
        return;
    }

    std::string id(idStr);
    auto manager = Manager::GetInstance();
    if ((manager != nullptr) && (nativeXComponent != nullptr)) {
        manager->SetNativeXComponent(id, nativeXComponent);
        auto container = manager->GetContainer(id);
        if (container != nullptr) {
            container->RegisterCallback(nativeXComponent);
            //            container->Export(env, exports);
        }
    }
}

void Manager::SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent) {
    if (nativeXComponent == nullptr) {
        return;
    }

    if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
        nativeXComponentMap_[id] = nativeXComponent;
        return;
    }

    if (nativeXComponentMap_[id] != nativeXComponent) {
        OH_NativeXComponent *tmp = nativeXComponentMap_[id];
        delete tmp;
        tmp = nullptr;
        nativeXComponentMap_[id] = nativeXComponent;
    }
}

void Manager::SetNativeNode(std::string &id, ArkUI_NodeHandle node) {
    if (node == nullptr) {
        return;
    }

    if (nativeNodeMap_.find(id) == nativeNodeMap_.end()) {
        nativeNodeMap_[id] = node;
        return;
    }

    if (nativeNodeMap_[id] != node) {
        ArkUI_NodeHandle tmp = nativeNodeMap_[id];
        delete tmp;
        tmp = nullptr;
        nativeNodeMap_[id] = node;
    }
}

OH_NativeXComponent *Manager::GetNativeXComponent(const std::string &id) {
    return nativeXComponentMap_[id];
}

ArkUI_NodeHandle Manager::GetNativeNode(const std::string &id) {
    return nativeNodeMap_[id];
}

Container *Manager::GetContainer(std::string &id) {
    if (containerMap_.find(id) == containerMap_.end()) {
        Container *instance = Container::GetInstance(id);
        containerMap_[id] = instance;
        return instance;
    }

    return containerMap_[id];
}
} // namespace NativeXComponentSample
